package com.atguigu.gmall.order.controller;

import com.atguigu.gmall.cart.client.CartFeignClient;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.common.util.AuthContextHolder;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.order.service.OrderInfoService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api/order")//结算时查询，在结算跳转时查询
public class OrderApiController {

    //order远程调用cart微服务，启用拦截器，在order服务中设置拦截配置
    @Resource
    private CartFeignClient cartFeignClient;
    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private OrderInfoService orderInfoService;

    //获取清单      远程调用，多模块间访问
    @GetMapping("/auth/trade")
    public Map<String, Object> trade(HttpServletRequest request) {
        Map<String, Object> orderMap = new HashMap<>();
        //1、查询商品清单
        List<CartInfo> cartListCecked = cartFeignClient.getCartListCecked();
        //订单页面显示的商品详情取自order-detail匹配，偷梁换柱
        List<OrderDetail> orderDetailList = cartListCecked.stream().map(cartInfo -> {
            OrderDetail detail = new OrderDetail();
            detail.setSkuId(cartInfo.getSkuId());
            detail.setSkuName(cartInfo.getSkuName());
            detail.setImgUrl(cartInfo.getImgUrl());
            detail.setOrderPrice(cartInfo.getSkuPrice());
            detail.setSkuNum(cartInfo.getSkuNum());
            return detail;
        }).collect(Collectors.toList());
        orderMap.put("detailArrayList", orderDetailList);
        //2.1、结算处确认之总件数
        long totalNum = orderDetailList.stream().collect(
                Collectors.summarizingInt(OrderDetail::getSkuNum)).getSum();
        orderMap.put("totalNum", totalNum);
        //2.2、结算处确认之总金额
        BigDecimal totalAmount = new BigDecimal(0);
        for (OrderDetail orderDetail : orderDetailList) {
            BigDecimal orderPrice = orderDetail.getOrderPrice();
            //当前总金额 + 商品价格 * 商品数量
            totalAmount = totalAmount.add(orderPrice.multiply(new BigDecimal(orderDetail.getSkuNum())));
        }
        orderMap.put("totalAmount", totalAmount);
        //3、生成交易号       提交订单时点击触发，k取自触发的方法
        String tradeNo = UUID.randomUUID().toString().replaceAll("-", "");//随机交易号，绑定用户id
        String userId = AuthContextHolder.getUserId(request);
        //交易号更新到缓存中
        redisTemplate.opsForValue().set("tradeNo" + userId, tradeNo);
        orderMap.put("tradeNo", tradeNo);
        return orderMap;
    }

    //提交订单      异步请求
    //前端页面方法处可获取为post方法，并传入order&tradeNo交易号
    @PostMapping("/auth/submitOrder")
    public Result submitOrder(
            @RequestBody OrderInfo orderInfo,
            String tradeNo,//交易流水号为提交时生成，非前端页面传入，不用写注解
            HttpServletRequest request) {
        String userId = AuthContextHolder.getUserId(request);
        //1、校验交易号是否正确，防止二次提交，幂等性等问题
        //交易号空
        if (StringUtils.isEmpty(tradeNo)){
            return Result.fail().message("非法操作");
        }
        //交易号不为空，与缓存中保存的进行对比
        Object redisTradeNo = redisTemplate.opsForValue().get("tradeNo" + userId);
        //已经提交，匹配情况会清掉该缓存
        if (redisTradeNo == null) {
            return Result.fail().message("请勿重复提交");
        }
        //不匹配
        else if (!redisTradeNo.equals(tradeNo)) {
            return Result.fail().message("非法操作");
        }
        //匹配
        redisTemplate.delete("tradeNo"+userId);
        //2、校验库存
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        //订单中商品列表空
        if (!CollectionUtils.isEmpty(orderDetailList)){
            //逐条校验库存
            for (OrderDetail orderDetail : orderDetailList) {
                boolean flag = orderInfoService.hasStock(orderDetail.getSkuId(),orderDetail.getSkuNum());
                //返回值   有库存：1   无库存：0
                if (!flag) {
                    return Result.fail().message(orderDetail.getSkuName()+"此商品已售完");
                }
            }
        }
        //3、验证无误，将传入的OrderInfo存入缓存及数据库
        Long orderId = orderInfoService.submitOrder(orderInfo);
        return Result.ok(orderId);
    }

    //根据订单id获取订单信息
    @GetMapping("/getOrderInfo/{orderId}")
    public OrderInfo getOrderInfo(@PathVariable Long orderId){
        return orderInfoService.getOrderInfo(orderId);
    }
}
